﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace DiscoveryLogic.Workflows.Components.Markov.MaxEnt
{
    /// <summary>
    /// A reader for GIS models stored in the binary format produced by the java version
    /// of MaxEnt.  This binary format stores data using big-endian values, which means
    /// that the C# version must reverse the byte order of each value in turn, making it
    /// less efficient.  Use only for compatibility with the java MaxEnt library.
    /// </summary>
    public class JavaBinaryGisModelReader : GisModelReader
    {
        private Stream mInput;
        private byte[] mBuffer;
        private int mStringLength = 0;
        private System.Text.Encoding mEncoding = System.Text.Encoding.UTF8;

        /// <summary>
        /// Constructor which directly instantiates the Stream containing
        /// the model contents.
        /// </summary>
        /// <param name="dataInputStream">The Stream containing the model information.
        /// </param>
        public JavaBinaryGisModelReader(Stream dataInputStream)
        {
            using (mInput = dataInputStream)
            {
                mBuffer = new byte[256];
                base.ReadModel();
            }
        }

        /// <summary>
        /// Constructor which takes a filename and creates a reader for it.
        /// </summary>
        /// <param name="fileName">The full path and name of the file in which the model is stored.
        /// </param>
        public JavaBinaryGisModelReader(string fileName)
        {
            using (mInput = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                mBuffer = new byte[256];
                base.ReadModel();
            }
        }

        /// <summary>
        /// Reads a 32-bit signed integer from the model file.
        /// </summary>
        protected override int ReadInt32()
        {
            mInput.Read(mBuffer, 0, 4);
            Array.Reverse(mBuffer, 0, 4);
            return BitConverter.ToInt32(mBuffer, 0);
        }

        /// <summary>
        /// Reads a double-precision floating point number from the model file.
        /// </summary>
        protected override double ReadDouble()
        {
            mInput.Read(mBuffer, 0, 8);
            Array.Reverse(mBuffer, 0, 8);
            return BitConverter.ToDouble(mBuffer, 0);
        }

        /// <summary>
        /// Reads a UTF-8 encoded string from the model file.
        /// </summary>
        protected override string ReadString()
        {
            //read string from binary file with UTF8 encoding
            mStringLength = (mInput.ReadByte() * 256) + mInput.ReadByte();
            mInput.Read(mBuffer, 0, mStringLength);
            return mEncoding.GetString(mBuffer, 0, mStringLength);
        }
    }
}
